/***********************************************************************************************************************
*
*        TWI = I2C
*
*        Versie 0.2  29/04/2010
*        Alle Registers van TWI opnieuw ingesteld.
*
*        Versie 0.4  16/05/2010
*        Alle Registers van TWI opnieuw ingesteld.
*        TWI afgerond.
*
*        Versie 0.5  20/05/2010
*        Interrupt enabled, Beginnen aan de EEPROM.
*
*        Versie 0.6  21/05/2010
*        LCD instellingen gedaan, begonnen aan instellen data overdracht.
*
*        Versie 0.7  27/05/2010
*        LCD programma aangepast (ACK's)
*
*
*
***********************************************************************************************************************/

#include <mod/include/TWI.h>

//TWI Clock Waveform Generator Register
unsigned int CLDIV = 0x00000010;    //Clock Low Divider 
unsigned int CHDIV = 0x00000010;    //Clock High Divider
unsigned int CKDIV = 0x00000003;    //Clock Divider

/**	@fn		TWI_Init()
	@brief	sets registers to enable TWI communication
	@return void
	*/
void TWI_Init(void){
	//Power Management
  p_pPMC->PMC_PCER |= PID9;         //PID9 (TWI) Peripheral Clock Enable
	
  //Peripheral Input/Output
  p_pPIO->PIO_PPUDR |= TWI_IO;      //PIO Pull Up Disable op TWI_IO lijnen
	p_pPIO->PIO_PDR |= TWI_IO;        //PIO Controller Disable op TWI_IO lijnen
	
  //TWI Clock Waveform Generator
  p_pTWI->TWI_CWGR  = 0;            //clear
	p_pTWI->TWI_CWGR |= CKDIV<<16;  	//CKDIV  Clock Divider
	p_pTWI->TWI_CWGR |= CHDIV<<8;   	//CHDIV  Clock High Divider
	p_pTWI->TWI_CWGR |= CLDIV;      	//CLDIV  Clock Low Divider          
	
  p_pTWI->TWI_CR    = MSEN;       	//TWI Master Transfer Enabled
	p_pTWI->TWI_MMR   = 0x00;       	//Master Mode Register --> Master write direction.
	p_pTWI->TWI_IADR  = 0;          	//TWI Internal Address Register
}

/**	@fn		TWI_Write(data)
	@brief	writes data to TWI interface
	@return void
	*/
void TWI_Write(unsigned int data){
	while(!(p_pTWI->TWI_SR & 0x04));	//Check TXRDY Transmit Holding Register Ready.
	p_pTWI->TWI_THR = data;				    //Schrijf data in het Transmit Holding Register.
}

/**	@fn		TWI_Reset()
	@brief	resets the TWI module
	return	void
	*/
void TWI_Reset(void){
	p_pTWI->TWI_CR = 0x80;            //Schrijf data in het Transmit Holding Register.
}

/**	@fn		TWI_Read()
	@brief	reads information from the TWI interface
	@return	data
	*/
int TWI_Read(void){
	volatile unsigned long int loop;
	loop=0;
	
	while((!(p_pTWI->TWI_SR & 0x02))&&(loop<5000000)){
	//while(!(p_pTWI->TWI_SR & 0x02));
		loop++;
	}
	
	if(loop<5000000){
		loop=p_pTWI->TWI_RHR;
		return(p_pTWI->TWI_RHR);
		//Check RXRDY, return TWI_RHR.
	}else{
		return(-1);                     //If not RXRDY, return -1. 
	}
}

/** @fn TWI_Start(adress, RNW)
    @brief  
    @param  adress  the TWI adress (DADR) to write to
    @param  RNW     RNW != 0 to read, RNW == NULL to write
    @return void
*/
void TWI_Start(unsigned int adress,unsigned int RNW){
  //clear addr and set slave addr
  p_pTWI->TWI_MMR &= ~0xFF0000;         //clear slave adress gebied (DADR)
  p_pTWI->TWI_MMR &= ~0x300;            //clear adress gebied (IADRSZ)
  p_pTWI->TWI_MMR |= (adress&0x7F)<<16; //zet slave adress (shift naar DADR)
  
  if(RNW){                              //check read/write
    p_pTWI->TWI_MMR |= 0x01000;         //Stel module op read in
  }else{
    p_pTWI->TWI_MMR &= ~0x01000;        //Stel module op write in
  }

  p_pTWI->TWI_CR |= START;              //Zet start condition.
}

/** @fn TWI_Start1(adress, RNW, *adresses, amount)
    @brief
    @param adress
    @param RNW
    @param *adresses   pointer to the array of the 8-bit addresses (chars) to be written
    @amount       IADRSZ (Internal Device Address Size) - range from 0 to 3 (0 equals no internal device addr, 3 is 3-byte internal device addr).
    @return
    */
/*void TWI_Start1(unsigned char adress,unsigned char RNW,unsigned char *adresses,unsigned char amount){
  unsigned char loop;
  unsigned long int status;
  
  //clear addr and set slave addr
  p_pTWI->TWI_MMR   &=~ 0xFF0000;         //clear slave adress gebied (DADR)
  p_pTWI->TWI_MMR &= ~0x300;              //clear adress gebied (IADRSZ)
  p_pTWI->TWI_MMR   |= (adress&0x7F)<<16; //zet slave adress (DADR)
  
  if(RNW){                                //check read/write
    p_pTWI->TWI_MMR   |= 0x01000;         //Stel module op read in
  }else{
    p_pTWI->TWI_MMR   &=~0x01000;         //Stel module op write in
  }
  
  p_pTWI->TWI_MMR |= (amount&0x03)<<8;    //Set internal device addr size to amount
  
  p_pTWI->TWI_IADR = 0;                   //clear internal device reg
  for(loop=0;loop<amount;loop++){
    p_pTWI->TWI_IADR |= (*(adresses+loop))<<(loop*8); //Set internal device addr to the addresses in the array
  }
  status=p_pTWI->TWI_IADR;
  p_pTWI->TWI_CR    |= START;             //Zet start condition.
}*/

/** @fn TWI_Repeated_Start()
    @brief  sends a START condition
    @return void
    */
void TWI_Repeated_Start(void){            //Repeated start is nogmaals een startpuls te versturen.
  p_pTWI->TWI_CR    |= START;             //START condition
}
 
/** @fn TWI_Stop()
    @brief  sends a STOP condition
    @return void
    */
 void TWI_Stop(void){
  p_pTWI->TWI_CR     = STOP;              //Stop condition
}

/** @fn TWI_Data_Ready()
    @brief  returns NULL untill there is data waiting on the TWI input
    @return NULL if no data, 1 if there is data ready
    */
int TWI_Data_Ready(void){
  return(p_pTWI->TWI_SR & 0x02);          //Stop condition
}

